﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using NVelocity.Runtime;
using NVelocity.App;
using NVelocity.Context;

using NVelocity;
using System.IO;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Text;
using Commons.Collections;
using System.Collections.Generic;
using System.Collections;
using System.Data.SqlClient;
using System.Threading;
using Microsoft.VisualBasic;
using System.Net;
using System.Collections.Specialized;
using FluorineFx.Json;
using System.Dynamic;
using Microsoft.CSharp;
using System.Linq;


namespace lxwmvc
{
    /// <summary>
    /// 获取配置参数
    /// </summary>
    public struct CONIFG
    {
        /// <summary>
        /// defaultcontroller
        /// </summary>
        public static string defaultcontroller = ConfigurationManager.AppSettings["defaultcontroller"];
        /// <summary>
        /// defaultaction
        /// </summary>
        public static string defaultaction = ConfigurationManager.AppSettings["defaultaction"];
        /// <summary>
        /// defaultcity_key
        /// </summary>
        public static string defaultcity_key = ConfigurationManager.AppSettings["defaultcity_key"];
        /// <summary>
        /// defaultcity_controller
        /// </summary>
        public static string defaultcity_controller = ConfigurationManager.AppSettings["defaultcity_controller"];
        /// <summary>
        /// defaultcity_action
        /// </summary>
        public static string defaultcity_action = ConfigurationManager.AppSettings["defaultcity_action"];
        /// <summary>
        /// defaultpage_key
        /// </summary>
        public static string defaultpage_key = ConfigurationManager.AppSettings["defaultpage_key"];
        /// <summary>
        /// defaultpage_controller
        /// </summary>
        public static string defaultpage_controller = ConfigurationManager.AppSettings["defaultpage_controller"];
        /// <summary>
        /// defaultpage_action
        /// </summary>
        public static string defaultpage_action = ConfigurationManager.AppSettings["defaultpage_action"];

        /// <summary>
        /// 是否需要扫描权限
        /// </summary>
        public static bool default_quanxian = ConfigurationManager.AppSettings["default_quanxian"].tostr() == "true";
    }

    /// <summary>
    /// 参数编程应用类型的
    /// </summary>
    public class WHERE
    {
        /// <summary>
        /// 内部字符串
        /// </summary>
        public string where = "";
    }
    /// <summary>
    /// 核心上下文信息
    /// </summary>
    public class pagebase : IDisposable
    {
        private static VelocityEngine velocity = null;
        private IContext context = null;
        private bool _cancelview = false;
        private bool _cancellayout = false;
        private bool _exit = false;


        /// <summary>
        /// 返回参数
        /// </summary>
        public string[] Arg
        {
            get {
                return (String[])Context.Items["_arg_"];
            }
            
        }
        
        /// <summary>
        /// 权限设置到SESSION里面，以后可以考虑其他形式存储
        /// </summary>
        public static string PowerString
        {
            get
            {
                return HttpContext.Current.Session["PowerString"].tostr();
            }
            set
            {
                HttpContext.Current.Session["PowerString"] = value;
            }
        }

        /// <summary>
        /// 布局名称
        /// </summary>
        private string layoutname = "";
        /// <summary>
        /// 模板名称
        /// </summary>
        private string _viewname = "";

        /// <summary>
        /// 默认控制器
        /// </summary>
        string defaultcontroller = CONIFG.defaultcontroller;
        /// <summary>
        /// 默认方法
        /// </summary>
        string defaultaction = CONIFG.defaultaction;

   
        /// <summary>
        /// 线程安全
        /// </summary>
        readonly static object[] syn = new object[0] { };
        
        /// <summary>
        /// 同步方法，只阻塞当前方法
        /// </summary>
        public static object m_monitorObject = new object();
        static Mutex m_mutex = new Mutex();//全局阻塞

        /// <summary>
        /// 不使用模板，其实在系统中，如果没有模板，系统也不会出现错误，他会自动不显示模板
        /// </summary>
        public void cancelview()
        {
            _cancelview = true;
        }

        /// <summary>
        /// 退出程序，后续不要再进行操作。
        /// </summary>
        public void exit()
        {
            _exit = true;
            //throw new Exception("MMM:人工终止操作！");
        }

        /// <summary>
        /// 改变vm名称
        /// </summary>
        /// <param name="vm">不能带后缀 .htm</param>
        public void randerview(string vm)
        {
            //不能带后缀
            _viewname = vm;
        }

        /// <summary>
        /// 设置layout名称
        /// </summary>
        /// <param name="layout">layout名称</param>
        public void setlayout(string layout)
        {
            //重新设置layout
            layoutname = layout;
        }

        /// <summary>
        /// 不使用布局
        /// </summary>
        public void cancellayout()
        {
            _cancellayout = true;
        }

        string strcontroller = string.Empty;
        string straction = string.Empty;
        string strarea = string.Empty;

        /// <summary>
        /// 设置cookies的作用域
        /// </summary>
        public static string cookies_domain = "";
        /// <summary>
        /// 设置cookies的过期时间
        /// </summary>
        public static double cookies_expires = 0;
        /// <summary>
        /// 可以外部设置用户主键的键
        /// </summary>
        public static string cookies_userid_key = "user_id";
        /// <summary>
        /// 判断用户是否已经登录
        /// </summary>
        public static int? UserId
        {
            get
            {
                var uid = cookieshelper.getcookie(cookies_userid_key, cookies_domain);
                if (string.IsNullOrEmpty(uid))
                    return default(int?);
                else
                {
                    //通过用户，得到用户对应的角色
                    if (string.IsNullOrEmpty(PowerString) || uid == "-999")
                    {
                        //重新初始化一下
                        applicationhelper.initmenupower();

                        //-999代表管理员
                        if (uid == "-999")
                        {
                            powerhelper.setpowerstring(uid);
                        }
                        else
                        {
                            string sql = "select * from sysyonghu where sysyonghuid=@0";
                            var t = queryhelper.get<supermodel>(sql, uid);

                            if (t != null)
                            {
                                powerhelper.setpowerstring(t["juese"].tostr(), t["juese1"].tostr());
                            }
                        }
                    }

                    return (int?)uid.toint32();
                }
            }
            set {
                if (!value.HasValue)
                {
                    //立刻过期
                    cookieshelper.delcookie(cookies_userid_key, cookies_domain);
                    return;
                }

                if (value == -999)
                    powerhelper.setpowerstring("-999");
                else
                {
                    //设置权限
                    string sql = "select * from sysyonghu where sysyonghuid=@0";
                    var t = queryhelper.get<supermodel>(sql, value.Value);

                    if (t != null)
                    {
                        powerhelper.setpowerstring(t["juese"].tostr(), t["juese1"].tostr());
                    }
                }

                cookieshelper.setcookie(cookies_userid_key, value.Value.tostr(), cookies_domain, cookies_expires);
            }
        }


        /// <summary>
        /// 加入helper
        /// lxwmvc.Helpers.xxxhelper
        /// </summary>
        /// <param name="name"></param>
        public void addhelper(string name)
        {
            var t = applicationhelper.lxwmvcdll.Assembly.GetType(name);
            var _instance = Activator.CreateInstance(t);
            this[name.Split('.')[name.Split('.').Length - 1].ToLower()] = _instance;
        }

        /// <summary>
        /// 根据主键得到信息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tablename"></param>
        /// <param name="qianzhun"></param>
        /// <returns></returns>
        public T getdbmodel<T>(string tablename = "", string qianzhun = "")
            where T : supermodel, new()
        {
            try
            {
                return getmodel<T>(tablename, qianzhun).select<T>();
            }
            catch { }
            return default(T);
        }

        /// <summary>
        /// 获取model
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="qianzhun"></param>
        /// <returns></returns>
        public T getmodel<T>(string tablename = "", string qianzhun = "") 
            where T: supermodel, new()
        {
            var model = Activator.CreateInstance<T>();

            var arrs = new List<NameValueCollection>();
            if (Post) arrs.Add(Request.Form);
            arrs.Add(Request.QueryString);
            {
                foreach (var arr in arrs)
                {
                    foreach (string s in arr.Keys)
                    {
                        if (!string.IsNullOrEmpty(s))//&& !s.Equals(key, StringComparison.OrdinalIgnoreCase))
                        {
                            if (qianzhun == "")
                                model[s] = getonevalue(s);
                            else
                            {
                                if (s.StartsWith(qianzhun, StringComparison.OrdinalIgnoreCase))
                                {
                                    string key = s.Substring(qianzhun.Length).ToLower();
                                    if (key.StartsWith(".") || key.StartsWith("_") || key.StartsWith(">")) key = key.Substring(1);//如果是._> 直接去除
                                    model[key] = getonevalue(s);
                                }
                            }
                        }
                    }
                }
            }

            string keys = v_s("_lxw_column_checkbox_").ToLower();
            foreach (string s in keys.Split(','))
            {
                if (s.Length == 0) continue;
                if (model.Contains(s))  //这里是写死了，如果允许，就是1，不允许就是0，只有两种状态，是否允许再数据库中配置一下？
                    model[s] = 1;//只要提交上来，肯定是存在内容，就认为是1
                else
                    model[s] = 0;
            }

            //这里存在问题，默认值的设置，可能是默认时间，也可能是默认的内容，就是不填写，默认是什么？
            //checkbox的问题

            //这里给日期设置默认值
            //string datetimes = requesthelper.getonevalue("_lxw_column_datetime_");
            //foreach (string s in datetimes.Split(','))
            //{
            //    if (s.Length == 0) continue;
            //    if (has.Contains(s))  //这里是写死了，如果允许，就是1，不允许就是0，只有两种状态，是否允许再数据库中配置一下？
            //        has[s] = 1;//只要提交上来，肯定是存在内容，就认为是1
            //    else
            //        has[s] = 0;
            //}
            


            return model;
        }




        /// <summary>
        /// 可能再次使用
        /// </summary>
        Type currenttype = null;

        /// <summary>
        /// 外部执行内部方法 20121025
        /// </summary>
        /// <param name="fun"></param>
        /// <param name="arg"></param>
        /// <returns></returns>
        public string customfun(string fun, params object[] arg)
        {
            if (currenttype == null) return "";
            var currentmethod_ = getmethod(currenttype, fun);

            if (currentmethod_ == null) return "";
            if (arg == null || arg.Length == 0)
                FastInvokeUtility.GetMethodInvoker(currentmethod_).Invoke(null, new object[] { this });
            else
                FastInvokeUtility.GetMethodInvoker(currentmethod_).Invoke(null, new object[] { this, arg });

            return "";
        }

        /// <summary>
        /// 页面加载核心函数
        /// </summary>
        /// <param name="_context"></param>
        public void execute(HttpContext _context)
        {
            try
            {
                //Request.ContentEncoding = Encoding.UTF8;
                Request = _context.Request;
                Response = _context.Response;
                Session = _context.Session;
                Server = _context.Server;
                Context = _context;

                strcontroller = _context.Items["_controller_"].ToString();
                straction = _context.Items["_action_"].ToString();
                strarea = _context.Items["_area_"].ToString();

                //默认controller
                if (strcontroller == "_defaultcontroller_")
                {
                    strcontroller = defaultcontroller;
                    //分站功能
                    if (applicationhelper.citypage != null && applicationhelper.citypage.ContainsKey(straction))
                    {
                        Context.Items[CONIFG.defaultcity_key] = applicationhelper.citypage[straction];

                        strcontroller = CONIFG.defaultcity_controller;
                        straction = CONIFG.defaultcity_action;
                    }

                    //查找单独系统页面 20120727,可能存在问题，20121024
                    if (applicationhelper.syspages != null && applicationhelper.syspages.ContainsKey(straction))
                    {
                        Context.Items[CONIFG.defaultpage_key] = applicationhelper.syspages[straction];

                        strcontroller = CONIFG.defaultpage_controller;
                        straction = CONIFG.defaultpage_action;
                    }
                }

                if (straction == "_defaultaction_")
                    straction = defaultaction;

                if (!string.IsNullOrEmpty(straction))
                {
                    context = new VelocityContext();
                }
                //代表是通用controller功能
                if (strarea == "table")
                {
                    //交换一下
                    settable(strcontroller);
                    strcontroller = strarea;
                }

                _viewname = straction;


                MethodInfo currentmethod = null;
                var dll = "velocity_lxwmvcdll";
                if (strcontroller == "table") dll = "velocity_lxwmvccore";
                //这里可能会存在问题
                currenttype = Type.GetType("lxwmvc." + strcontroller + "controller," + dll);
                if (currenttype == null)
                    throw new Exception("lxwmvc." + strcontroller + "controller," + dll + ":controller没有找到!");

                currentmethod = getmethod(currenttype, straction, ref straction);
                //得到真实的
                _viewname = straction;

                List<Attribute> actionattribute = new List<Attribute>();
                if (currentmethod != null)
                {
                    object[] attrs = currentmethod.GetCustomAttributes(false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        foreach (var o in attrs)
                        {
                            actionattribute.Add(o as Attribute);
                        }
                    }
                }


                if (currenttype != null)
                {
                    object[] attrs = currenttype.GetCustomAttributes(false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        foreach (var o in attrs)
                        {
                            actionattribute.Add(o as Attribute);
                        }
                    }
                }

                object log = null;
                //判断是否需要验证权限这部分功能
                if (CONIFG.default_quanxian)
                {
                    //判断权限和菜单
                    var quanxian1 = actionattribute.Find(o => o.GetType() == typeof(caidanAttribute));

                    var quanxian2 = actionattribute.Find(o => o.GetType() == typeof(quanxianAttribute));
                    var quanxian3 = actionattribute.FindAll(o => o.GetType() == typeof(yilaiAttribute));

                    //quanxian1 = null;
                    //quanxian2 = null;
                    //quanxian3 = null;

                    //获取用户ID和权限
                    var uid = UserId;

                    //如果不设置，代表不受限制
                    if (quanxian1 != null)
                    {
                        log = quanxian1;
                        if (!findstr(PowerString, "@" + strcontroller + "@" + straction + ""))
                            throw new Exception("AAA1:没有权限!");
                    }
                    if (quanxian2 != null)
                    {
                        log = quanxian2;
                        if (!findstr(PowerString, "@" + strcontroller + "@" + straction + ""))
                            throw new Exception("AAA2:没有权限!");
                    }
                    if (quanxian3 != null)
                    {
                        //如果是多个，只要依赖其中一个就可以，可以依赖菜单，也可以依赖权限
                        //依赖的东西必须存在
                        bool hasFind = quanxian3.Count == 0;
                        //string errMsg = "";
                        foreach (var qx in quanxian3)
                        {
                            string name = (qx as yilaiAttribute).quanxian_caidan.ToLower();
                            if (name.isnull()) continue;
                            //只有2中写法，一种是controller.action
                            //另外一种，就是action
                            var names = name.Split(new char[] { ',', '.', '>', '-' });
                            if (names.Length == 1) name = "@" + strcontroller + "@" + names[0].TrimStart('@');
                            if (names.Length == 2) name = "@" + names[0].TrimStart('@') + "@" + names[1].TrimStart('@');


                            if (!applicationhelper.QUANXIANS.ContainsKey(name)
                                   && !applicationhelper.CAIDANS.ContainsKey(name)
                                   )
                                throw new Exception("AAA310:依赖权限或者菜单“" + name + "”没有找到!");


                            if (applicationhelper.QUANXIANS.ContainsKey(name))
                            {
                                quanxian p1 = applicationhelper.QUANXIANS[name];
                                if (p1 != null) log = new quanxianAttribute(p1.mingcheng, p1.caidan);
                                if (p1 != null && findstr(PowerString, p1.biaoshi))
                                {
                                    //throw new Exception("AAA31:没有权限!");
                                    hasFind = true;
                                    break;
                                }
                            }
                            else
                            {
                                caidan p2 = applicationhelper.CAIDANS[name];
                                if (p2 != null) log = new caidanAttribute(p2.mingcheng);
                                if (p2 != null && findstr(PowerString, p2.biaoshi))
                                {
                                    //throw new Exception("AAA32:没有权限!");
                                    hasFind = true;
                                    break;
                                }
                            }
                        }

                        //这里比较特殊，当有多个依赖的时候
                        if (!hasFind)
                        {
                            throw new Exception("AAA32-AAA32:没有找到依赖的权限!");
                        }
                    }


                    {
                        //获取变态权限(这部分没有具体测试)
                        string name = strcontroller + "/" + straction;
                        if (strcontroller.ToLower() == "table") name = table + "/" + straction;
                        if (applicationhelper.YILAIS.ContainsKey(name.ToUpper()))
                        {
                            var l = applicationhelper.YILAIS[name.ToUpper()];
                            if (l[0] == "menu")
                            {
                                log = applicationhelper.CAIDANS["@" + l[1] + "@" + l[2]];
                                if (!findstr(PowerString, "@" + l[1] + "@" + l[2]))
                                    throw new Exception("AAA1_1:没有权限!");
                            }
                            if (l[0] == "power")
                            {
                                log = applicationhelper.QUANXIANS["@" + l[1] + "@" + l[2]];
                                if (!findstr(PowerString, "@" + l[1] + "@" + l[2]))
                                    throw new Exception("AAA2_1:没有权限!");
                            }
                            if (l[0] == "yilai")
                            {
                                foreach (var s in l[3].Split(','))
                                {
                                    log = applicationhelper.QUANXIANS[s];
                                    if (!findstr(PowerString, s))
                                        throw new Exception("AAA3_1:没有权限!");
                                }
                            }
                        }
                    }
                }

                var trans = actionattribute.Find(o => o.GetType() == typeof(transAttribute));
                if (trans != null) sqlhelper.starttranscation(trans);

                var _init = getmethod(currenttype, "_init");
                //这句话非常重要
                if (_init != null) FastInvokeUtility.GetMethodInvoker(_init).Invoke(null, new object[] { this });


                //判断微信功能
                var weixin = actionattribute.Find(o => o.GetType() == typeof(weixinAttribute));
                {
                    if (weixin != null)
                    {
                        var weixinObj = (weixin as weixinAttribute).instance;
                        var url = (weixin as weixinAttribute).url;
                        var scope = (weixin as weixinAttribute).scope;
                        //验证是否需要重定向
                        if (weixinObj.CheckUserInfo(url,scope))
                        {
                            //退出
                            _exit = false;
                        }
                    }
                }

                //如果是全局退出，就不要再执行后面的方法
                if (!_exit)
                {
                    //如果 log 不为空，就记录日志
                    if (log != null) savelog(log, currentmethod.DeclaringType.FullName);

                    var json = actionattribute.Find(o => o.GetType() == typeof(jsonAttribute));
                    Type jsontype = null;
                    if (json != null)
                    {
                        jsontype = ((jsonAttribute)json).jsontype;
                        _JSON = Activator.CreateInstance(jsontype);
                    }

                    var lc = actionattribute.FindAll(o => o.GetType() == typeof(tongbuAttribute));
                    if (lc == null || lc.Count == 0)
                    {
                        if (currentmethod != null)
                            FastInvokeUtility.GetMethodInvoker(currentmethod).Invoke(null, new object[] { this });
                    }
                    else
                    {
                        try
                        {
                            //加方法锁
                            m_mutex.WaitOne();
                            FastInvokeUtility.GetMethodInvoker(currentmethod).Invoke(null, new object[] { this });
                        }
                        catch (Exception err)
                        {
                            if (_JSON != null && _JSON.GetType() == typeof(BaseJson))
                            {
                                var _json = JSON<BaseJson>();
                                {
                                    _json.success = false;
                                    if (err.InnerException != null && !string.IsNullOrEmpty(err.InnerException.Message))
                                        _json.msg = err.InnerException.Message;
                                    else
                                        _json.msg = err.Message;
                                };
                            }
                            else//如果不是json模式，直接返回到顶层
                            {
                                throw err;
                            }
                        }
                        finally
                        {
                            m_mutex.ReleaseMutex();
                        }
                    }


                    //分页输出
                    dopager();

                    //如果不设置，是直接加载layout的
                    if (!_cancellayout)
                    {
                        //找方法上的
                        var layout = actionattribute.Find(o => o.GetType() == typeof(layoutAttribute));
                        if (layout != null)
                        {
                            layoutname = (layout as layoutAttribute).layoutname;
                        }
                    }

                    //输出helper信息
                    var helpers = actionattribute.FindAll(o => o.GetType() == typeof(helperAttribute));
                    foreach (helperAttribute o in helpers)
                    {
                        if (this.context.ContainsKey(o.helpertype.Name.ToLower())) continue;
                        this[o.helpertype.Name.ToLower()] = o.instance;
                    }


                    //把日期输出去
                    this["now"] = DateTime.Now;
                    this["this"] = this;

                    //把request输出出去
                    foreach (string s in Request.QueryString.Keys)
                    {
                        //如果已经存在，就不要输出出去了。
                        if (!context.ContainsKey(s))
                            this[s] = Request.QueryString[s];
                    }

                    //把全局helper压缩出去
                    this["formhelper"] = new formhelper();
                    this["funhelper"] = new funhelper();
                    this["stringhelper"] = new stringhelper();
                    this["request"] = Request;

                    

                    //随机数
                    this["random"] = "__i=" + Guid.NewGuid().ToString();
                    //把这个替换成$
                    this["_JQ_"] = "$";

                    //如果没有设置，系统默认设置这个值
                    if (!context.ContainsKey("formurl"))
                        this["formurl"] = requesthelper.formurl();

                    if (json != null)
                    {
                        Response.ContentType = "application/json";

                        var jsonString = JavaScriptConvert.SerializeObject(_JSON);
                        string p = @"new Date\((\d+)\)";
                        MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertJsonDateToDateString);
                        Regex reg = new Regex(p);
                        jsonString = reg.Replace(jsonString, matchEvaluator);
                        Response.Write(
                            jsonString
                        );
                    }
                    else
                    {
                        if (_viewname.IndexOf("\\") != -1 || _viewname.IndexOf("/") != -1)
                        {
                            //不能带后缀
                            display(_viewname);
                        }
                        else
                        {
                            if (table.Length > 0 && strcontroller == "table")
                                display(table + "\\" + _viewname);
                            else
                                display(strcontroller + "\\" + _viewname);
                        }
                    }
                }
                //统一提交事务
                sqlhelper.transactioncommit();
            }
            //[System.Threading.ThreadAbortException] = {由于代码已经过优化或者本机框架位于调用堆栈之上，无法计算表达式的值。}
            catch (ThreadAbortException)
            {
                //Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                Console.Write("ThreadAbortException");
            }
            catch (Exception err)
            {
                //错误信息
                //Response.StatusCode = (int)HttpStatusCode.InternalServerError;

                sqlhelper.transactionrollback();

                if (_exit == false)
                {
                    dataloger.fatal("", err);
                    string msg = geterror(err);
#if DEBUG
                    //write(msg.Replace("\n", "<br/>"));

                    write(err.Message);
#else
                    //跳转到一个错误页面

#endif
                }
            }
            finally
            {
                //释放session
                sqlhelper.dbconnectclose();
            }
        }

        /// <summary>
        /// 存储日志信息
        /// </summary>
        /// <param name="log"></param>
        /// <param name="fun"></param>
        private void savelog(object log,string fun)
        {
            var t = log.GetType();
            string name = t == typeof(caidanAttribute)
                ?(log as caidanAttribute).mingcheng
                :(log as quanxianAttribute).mingcheng;
            string leixing = t == typeof(caidanAttribute)
                ?"菜单"
                :"权限";

            //获取form信息，params信息，然后存储到数据中，以及IP地址等等
            var sql = "insert into sysrizhi(caozuoren,riqi,neirong,leixing,ip,canshu,fangfa) values(";
            sql += "'"+ (UserId.HasValue ? UserId.Value : -1)+"'";
            sql += ",getdate(),'"+name+"','"+leixing+"','"+requesthelper.clientip()+"','"+getparams().tosafe()+"','"+fun+"')";

            //插入日志
            queryhelper.execute(sql);
        }

        /// <summary>
        /// 获取请求的参数
        /// </summary>
        /// <returns></returns>
        private string getparams()
        {
            StringBuilder sb = new StringBuilder();
            if (Post)
            {
                if (Request.Form.Keys.Count > 0)
                {
                    sb.AppendLine("Form:");
                    foreach (string o in Request.Form.Keys)
                        sb.AppendLine(o + "=" + (Request.Form[o] == null ? "NULL" : Request.Form[o].tostr()));
                }
            }

            //查询添加
            if (Request.QueryString.Keys.Count > 0)
            {
                sb.AppendLine("QueryString:");
                foreach (string o in Request.QueryString.Keys)
                    sb.AppendLine(o + "=" + (Request.QueryString[o] == null ? "NULL" : Request.QueryString[o].tostr()));
            }

            return sb.tostr().Replace("\n","<br/>");
        }

        /// <summary>
        /// json日期转换
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        string ConvertJsonDateToDateString(Match m)
        {
            string result = string.Empty;
            DateTime dt = new DateTime(1970, 1, 1);
            dt = dt.AddMilliseconds(long.Parse(m.Groups[1].Value));
            dt = dt.ToLocalTime();
            result = dt.ToString("yyyy-MM-dd HH:mm:ss");
            return "\"" + result + "\"";
        }

        /// <summary>
        /// 获取页面传输过来的json对象
        /// </summary>
        public JavaScriptObject bodyjson()
        {
            StreamReader sb = new StreamReader(Request.InputStream, Encoding.UTF8);
            var content = sb.ReadToEnd();

            JavaScriptObject o2 = JavaScriptConvert.DeserializeObject(
                content
                ) as JavaScriptObject;

            return o2;
        }

        /// <summary>
        /// 返回body字符串
        /// </summary>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public string bodystring(Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;
            StreamReader sb = new StreamReader(Request.InputStream, encoding);
            var content = sb.ReadToEnd();

            return content;
        }

        /// <summary>
        /// 判断p1=true 然后抛出异常
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        public void ifcheck(bool p1, string p2)
        {
            if (p1) throw new Exception(p2);
        }

        /// <summary>
        /// 退出程序，后续不要再进行操作。
        /// </summary>
        public void exit(string msg = "MMM:人工终止操作！")
        {
            _exit = true;
            throw new Exception(msg);
        }

        string _STORE_PK_ = null;
        string _STORE_TABLE_ = null;
        string _STORE_JILIANTABLE_ = null;
        //string _STORE_JILIANWAIJIAN_ = null;
        /// <summary>
        /// 用于单表操作的主键
        /// </summary>
        public string pk
        {
            get { return _STORE_PK_ ?? v_s("_pk_"); }
            set { _STORE_PK_ = value; }
        }

        /// <summary>
        /// 默认输出json对象
        /// </summary>
        object _JSON = null;
        /// <summary>
        /// 输出json对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T JSON<T>()
        {
            return (T)_JSON;
        }

        /// <summary>
        /// 用于单表操作的表
        /// </summary>
        public string table
        {
            //get { return v_s(""); }
            get { return _STORE_TABLE_ ?? v_s("_table_"); }
            set { _STORE_TABLE_ = value; }
        }

        /// <summary>
        /// 级联
        /// </summary>
        public string[] jilians
        {
            //get { return v_s("_ji_lian_").Split('_'); }
            get { return (_STORE_JILIANTABLE_ ?? v_s("_ji_lian_")).Split('_'); }
            set { _STORE_JILIANTABLE_ = string.Join("_", value); }
        }

        /// <summary>
        /// 是否存在级联
        /// </summary>
        public bool hasjilian
        {
            get { return jilians.Length == 2; }
        }

        /// <summary>
        /// 设置级联
        /// </summary>
        /// <param name="zibiao">子表</param>
        /// <param name="zibiaowaijian">子表对应主键的外键</param>
        /// <returns></returns>
        public string setjilian(object zibiao, object zibiaowaijian)
        {
            return string.Format("_ji_lian_={0}_{1}", zibiao.tostr(), zibiaowaijian.tostr());
        }

        /// <summary>
        /// 自动装载数据++++++++
        /// </summary>
        public void autoloaddata(supermodel model, string key = "loadformdatas", Dictionary<string, string> di = null)
        {
            string keyvalues = "";
            if (model != null && model.Keys.Count > 0)
            {
                foreach (string k in model.Keys)
                {
                    if (k.IndexOf("=") != -1) continue;
                    //todo:lxw 20131101
                    keyvalues += k.ToLower() + ":\"" +
                        Strings.Replace(encodejscript(model[k].tostr()),
                        "script", "p", 1, -1, CompareMethod.Text) + "\",\n";
                    continue;
                }

                this[key] = model;
                //原来的key太不好记了。
                this["body"] = model;
            }
            if (di != null)
            {
                foreach (string k in di.Keys)
                {
                    if (k.IndexOf("=") != -1) continue;
                    keyvalues += k.ToLower() + ":\"" +
                       Strings.Replace(encodejscript(di[k].tostr()),
                       "script", "p", 1, -1, CompareMethod.Text) + "\",\n";
                    this[k] = di[k].tostr();
                }

            }
            keyvalues += "__end__:\"lxw\"";

            //把数据压出去
            this["loadformdata"] = "<script>\r\nvar DATA=\r\n{\r\n" + keyvalues + "\r\n}\r\n$(function(){loadform();});\r\n</script>";

        }

        /// <summary>
        /// 检查request中key是否为空，如果为空 抛出异常
        /// </summary>
        /// <param name="key"></param>
        /// <param name="msg"></param>
        public void check_empty(string key, string msg)
        {
            if (string.IsNullOrEmpty(v_s(key))) throw new Exception(msg);
        }
        /// <summary>
        /// 判断表达式是否正确，如果为真 抛出异常
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="msg"></param>
        public void iftrueerror(bool exp, string msg)
        {
            if (exp) throw new Exception(msg);
        }

        /// <summary>
        /// 编码javascript代码
        /// </summary>
        /// <param name="strJsMsg"></param>
        /// <returns></returns>
        public string encodejscript(string strJsMsg)
        {
            Regex re = new Regex("\\\\|\\\"|\\\r|\\\n|\\\'|\\<|\\>|\\&", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
            return re.Replace(strJsMsg, new MatchEvaluator(encodejscript));
        }

        string encodejscript(Match m)
        {
            int code = (int)m.Value[0];
            string chars = "0123456789ABCDEF";
            int a1 = code & 0xF;
            int a2 = (code & 0xF0) / 0x10;
            // int   a3=(code&0xF00)/0x100;  
            // int   a4=(code&0xF000)/0x1000;  
            // return   "\\u"+chars[a4]+chars[a3]+chars[a2]+chars[a1];  
            return "\\x" + chars[a2] + chars[a1];
        }

        string geterror(Exception lastException)
        {
            StringBuilder sb = new StringBuilder();
            geterrormsg(sb, lastException);

            return (sb.ToString());
        }

        /// <summary>
        /// 执行一条语句得到字段的内容
        /// </summary>
        /// <param name="table"></param>
        /// <param name="name"></param>
        /// <param name="idvalue"></param>
        /// <returns></returns>
        public string getname(object table, object name, object idvalue)
        {
            //修正，不一定正确，好像还存在隐患
            string sql = "select top 1 {0} from {1} where cast({2} as nvarchar(50))='{3}'";
            return queryhelper.get<string>(string.Format(sql, name, table, supermodel.pks[table+""], idvalue)).tostr();
        }

        /// <summary>
        /// 为了解决再循环中多次查找数据的的问题
        /// </summary>
        /// <param name="table">表名</param>
        /// <param name="name">查询的字段</param>
        /// <param name="models">遍历的集合</param>
        /// <param name="guanlianid">集合对应的外键</param>
        public void innerstr(object table, object name, IEnumerable<supermodel> models, string guanlianid = "")
        {
            _inner(table, name, models, guanlianid, "'");
        }
        /// <summary>
        /// 设置int组合
        /// </summary>
        /// <param name="table">表名</param>
        /// <param name="name">查询的字段</param>
        /// <param name="models">遍历的集合</param>
        /// <param name="guanlianid">集合对应的外键</param>
        public void innerint(object table, object name, IEnumerable<supermodel> models, string guanlianid = "")
        {
            _inner(table, name, models, guanlianid, "");
        }
        /// <summary>
        /// 设置关联查询方式
        /// </summary>
        /// <param name="table">表名</param>
        /// <param name="name">查询的字段</param>
        /// <param name="models">遍历的集合</param>
        /// <param name="guanlianid">集合对应的外键</param>
        /// <param name="split"></param>
        private void _inner(object table, object name, IEnumerable<supermodel> models, string guanlianid = "", string split = "'")
        {
            string key = supermodel.pks[table.tostr()];
            if (string.IsNullOrEmpty(guanlianid)) guanlianid = key;

            string where = " in (" + split + "-10000" + split + "";
            foreach (supermodel dr in models)
            {
                var v = dr[guanlianid].tostr();
                if (v.isnull()) continue;
                where += "," + split + "" + dr[guanlianid].tostr().Replace("'", "''") + "" + split + "";
            }
            where += ")";

            string sql = "select {0} as 'newvalue',{1} as 'newkey' from {2} where {1} {3}";
            //暂时存储起来
            this[table + "_" + name] = queryhelper.query<supermodel>(string.Format(sql, name, key, table, where));
        }
        /// <summary>
        /// 获取值
        /// </summary>
        /// <param name="table">表名</param>
        /// <param name="name">查询的字段</param>
        /// <param name="guanlianid">集合对应的外键</param>
        /// <returns></returns>
        public string innervalue(object table, object name, object guanlianid)
        {
            try
            {
                IEnumerable<supermodel> models = (IEnumerable<supermodel>)this[table + "_" + name];
                foreach (supermodel model in models)
                    if (model["newkey"].tostr() == guanlianid.tostr())
                        return model["newvalue"].tostr();
            }
            catch { }
            return "";
        }
        /// <summary>
        /// 得到字典的名称
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public string getzidian(object id)
        {
            if (string.IsNullOrEmpty(id.tostr())) return "";
            try
            {
                string sql = "select top 1 mingcheng from syszidian where syszidianid=" + id.toint32(-1) + " ";
                return sqlhelper.get<string>(sql);
            }
            catch { } return id.tostr();
        }

        /// <summary>
        /// 通过字典产生options
        /// </summary>
        /// <param name="bianhao"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public string getoptions(object bianhao, string value = "")
        {
            string sql = "select * from syszidian where zidianleibie in (select sysyzidianleibieid from syszidianleibie where  bianhao='" + bianhao + "')";
            StringBuilder sb = new StringBuilder();
            var models = queryhelper.query<supermodel>(sql);
            foreach (supermodel dr in models)
            {
                sb.Append("<option value=" + dr["syszidianid"].tostr() + " " + (dr["syszidianid"].tostr().ToLower() == value.tostr().ToLower() ? "selected" : "") + ">" + dr["mingcheng"].tostr() + "</option>\r\n");
            }
            return sb.tostr();
        }



        /// <summary>
        /// 构造错误日志
        /// </summary>
        /// <param name="sb">存储错误日志</param>
        /// <param name="exception">错误信息</param>
        private void geterrormsg(StringBuilder sb, Exception exception)
        {
            sb.Append("错误类型:" + exception.GetType().Name + "\r\n");
            sb.Append("错误信息:" + exception.Message + "\r\n");

            if (!string.IsNullOrEmpty(exception.StackTrace))
                sb.Append("StackTrace:\r\n" + exception.StackTrace + "\r\n");

            if (exception.InnerException != null)
            {
                sb.Append("InnerException:\r\n");
                geterrormsg(sb, exception.InnerException);
            }
        }

        /// <summary>
        /// 得到方法体,也可以通过别名找
        /// </summary>
        /// <param name="type">type</param>
        /// <param name="name">method name</param>
        /// <param name="truename">action 真实名称</param>
        /// <returns></returns>
        MethodInfo getmethod(Type type, string name, ref string truename)
        {
            MethodInfo[] ms = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
            name = name.Trim();

            foreach (MethodInfo m in ms)
            {
                string bieming = m.Name;
                {
                    object[] attrs = m.GetCustomAttributes(typeof(biemingAttribute), false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        bieming = (attrs[0] as biemingAttribute).bieming;
                    }
                }

                //忽略大小写
                if (bieming.Trim().Equals(name.Trim(), StringComparison.OrdinalIgnoreCase))
                {
                    //别名作为新的vm文件
                    //_viewname = bieming.Trim();
                    truename = m.Name;// bieming.Trim();
                    return m;
                }
            }

            return null;
        }
        MethodInfo getmethod(Type type, string name)
        {
            return getmethod(type, name, ref name);
        }

        /// <summary>
        /// 没有值，或者转换失败，都用0代替，也可以自己设置
        /// </summary>
        /// <param name="key"></param>
        /// <param name="def"></param>
        /// <returns></returns>
        public int v_i(string key, int def = 0)
        {
            string value = getonevalue(key);
            try
            {
                if (value == null)
                {
                    //writelog("无法取到Request.Params[\"{0}\"]的数据!", key);
                    return def;
                }

                return value.toint32(def);
            }
            catch
            {
                dataloger.fatal(string.Format("[{0}]转换整数失败!", value));

                return def;
            }
        }

        /// <summary>
        /// 返回到上一页
        /// </summary>
        /// <param name="strmsg"></param>
        /// <param name="flag">true 代表跳转</param>
        public void back(string strmsg = "",bool flag = true)
        {
            string msg = "";
            if (!string.IsNullOrEmpty(strmsg)) msg = " alert('" + encodejscript(strmsg) + "'); ";
            if (flag) msg += "back();";
            //注意两侧使用的单引号字符串
            write(msg);
        }

        /// <summary>
        /// 得到上一个页面地址
        /// </summary>
        public string formurl
        {
            get
            {
                return requesthelper.formurl();
            }
        }

        /// <summary>
        /// 获取request里面的值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string v_s(string key)
        {
            string value = getonevalue(key);
            if (value == null)
            {
                //writelog("无法取到Request.Params[\"{0}\"]的数据!", key);
                return "";
            }

            return value;
        }
        /// <summary>
        /// 获取request里面的值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string v_ss(string key)
        {
            string value = getonevalue(key);
            if (value == null)
            {
                //writelog("无法取到Request.Params[\"{0}\"]的数据!", key);
                return "";
            }

            return value.Replace("'", "''").Split(';')[0];
        }
        /// <summary>
        /// 获取request里面的值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public decimal v_dec(string key)
        {
            string value = getonevalue(key);
            try
            {
                if (value == null)
                {
                    //writelog("无法取到Request.Params[\"{0}\"]的数据!", key);
                    return 0m;
                }

                return Convert.ToDecimal(value);
            }
            catch
            {
                dataloger.fatal(string.Format("[{0}]转换decimal失败!", value));

                return 0m;
            }
        }
        /// <summary>
        /// 获取request里面的值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public DateTime v_date(string key)
        {
            string value = getonevalue(key);
            try
            {
                if (value == null)
                {
                    //writelog("无法取到Request.Params[\"{0}\"]的数据!", key);
                    return new DateTime(1900, 1, 1);
                }

                return Convert.ToDateTime(value);
            }
            catch
            {
                dataloger.fatal(string.Format("[{0}]转换日期失败!", value));

                return new DateTime(1900, 1, 1);
            }
        }

        /// <summary>
        /// 获取上下文信息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T get<T>(string key)
        {            
            string obj = getonevalue(key);
            if (obj == null) return default(T);

            Type t = typeof(T);
            if (t == typeof(int))
                return (T)Convert.ChangeType(obj.toint32(), t);
            else if (t == typeof(decimal))
                return (T)Convert.ChangeType(obj.todecimal(), t);
            else if (t == typeof(string))
                return (T)Convert.ChangeType(obj.tostr(), t);
            else if (t == typeof(DateTime))
                return (T)Convert.ChangeType(obj.todatetime(), t);

            //http://www.csharpwin.com/csharpspace/12851r5551.shtml
            if (!typeof(T).IsGenericType)
            {
                return (T)Convert.ChangeType(obj, typeof(T));
            }
            Type genericTypeDefinition = typeof(T).GetGenericTypeDefinition();
            if (genericTypeDefinition == typeof(Nullable<>))
            {
                try
                {
                    return (T)Convert.ChangeType(obj, Nullable.GetUnderlyingType(typeof(T)));
                }
                catch {
                    if (obj == "") return default(T);
                }
            }


            throw new InvalidCastException(string.Format("无效的类型转换 \"{0}\" to type \"{1}\".",
                obj.GetType().FullName,
                typeof(T).FullName));
        }


        /// <summary>
        /// 系统初始化
        /// </summary>
        static pagebase()
        {
            velocity = new VelocityEngine();

            //ExtendedProperties props = new ExtendedProperties();
            //props.AddProperty(RuntimeConstants.RESOURCE_LOADER, "file");
            //props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, HttpContext.Current.Server.MapPath(templatDir));
            //props.AddProperty(RuntimeConstants.INPUT_ENCODING, "gb2312");
            //props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "gb2312");
            //velocity.Init(props);


            //使用设置初始化VelocityEngine

            ExtendedProperties props = new ExtendedProperties(HttpContext.Current.Server.MapPath("/nvelocity.properties"));
            props[RuntimeConstants_Fields.FILE_RESOURCE_LOADER_PATH] = HttpContext.Current.Server.MapPath(props[RuntimeConstants_Fields.FILE_RESOURCE_LOADER_PATH].ToString());
            velocity.Init(props);
        }




        const String _PAGESEARCH_NAME_ = "pagesearch";
        /// <summary>
        /// 在action="?$!{pagesort}"使用
        /// </summary>
        const String _PAGE_SORT_NAME_ = "pagesort";

        private string pagesearchdata = String.Empty;
        private string pagesortdata = String.Empty;

        /// <summary>
        /// 功能:分页需要传递到VM页面的参数
        /// [09.4.12 lxw]<para />
        /// </summary>
        /// <param name="blnencrypt">参数是否需要加密，如果加密的话，接收的时候就必须解密</param>
        public void dopager(bool blnencrypt)
        {
            if (pagesearchdata.isnotnull())
                pagesearchdata = pagesearchdata.TrimStart(new char[]{'&'});
           
            
            //如果没有数据，传递一个空的，再前面至少不会出现错误。
            if (pagesearchdata.Length == 0) pagesearchdata = "_=_";

            if (blnencrypt)
            {
                this[_PAGESEARCH_NAME_] = cryptohelper.encode(pagesearchdata);
                this[_PAGE_SORT_NAME_] = cryptohelper.encode(pagesortdata);
            }
            else
            {
                this[_PAGESEARCH_NAME_] = pagesearchdata;
                this[_PAGE_SORT_NAME_] = pagesortdata;
            }
        }

        /// <summary>
        /// 功能:参考DoPager(false),不加密参数
        /// [09.4.12 lxw]<para />
        /// </summary>
        void dopager()
        {
            dopager(false);
        }


        ///// <summary>
        ///// 解密ID类
        ///// </summary>
        //Regex MyRegex = new Regex(
        //    "\\(\\-([^\\-\\(\\)]+)\\-\\)",
        //  RegexOptions.IgnoreCase
        //  | RegexOptions.IgnorePatternWhitespace
        //  );


        /// <summary>
        /// 取request中对应键的值<para />
        /// blnSearch为True的是作为分页需要的字符串，但是如果blnHtml为true，blnSearch设置不起作用;<para />
        /// 功能:blnHtml值里面如果存在HTML格式<para />
        /// [09.4.12 lxw]<para />
        /// </summary>
        /// <param name="strkey">request.params[strKey]中的键</param>
        /// <param name="blnsearch">true:是否把值传递到分页中</param>
        /// <returns>返回对应request中key的value</returns>
        public String paramsvalue(String strkey, bool blnsearch = true)
        {
            string strvalue = getonevalue(strkey);// Request.Params[strKey];
            if (strvalue == null) return "";

            if (strvalue != "" && blnsearch)
            {
                this[strkey] = strvalue;
                insertpagevalue(strkey, strvalue);
            }

            //url解码
            return Server.UrlDecode(strvalue);
        }

        /// <summary>
        /// 获取传递过来的参数，并且输出到url连接字符串中，主要用于分页中
        /// </summary>
        /// <param name="strkey">获取数据</param>
        /// <returns>返回数据</returns>
        public string pagervalue(string strkey)
        {
            return paramsvalue(strkey, true);
        }

        /// <summary>
        /// 组合复杂一点的查询条件，传递的是具体的值，具体的值建议不是从前台捕获的参数
        /// </summary>
        /// <param name="strwhere"></param>
        /// <param name="strcolmun"></param>
        /// <param name="strvalue">传递具体的数据</param>
        /// <param name="orand"></param>
        /// <param name="express"></param>
        /// <param name="action"></param>
        /// <param name="orand_end"></param>
        public void queryvalue(ref String strwhere,
            String strcolmun,
            String strvalue,
             orand orand = orand.and,
            express express = express.dengyuzifuchuan,
            Action<WHERE> action = null,
            orand orand_end = orand.and)
        {
            dbdatehelper.querystring(ref strwhere, strcolmun, strvalue, orand, express);

            if (action != null)
            {
                WHERE where = new WHERE();
                action(where);
                if(where.where.isnotnull())
                    strwhere = strwhere + " " + Enum.GetName(typeof(orand), orand_end) + " (" + where.where + ")";
            }
        }

        /// <summary>
        /// 组合where条件，主要是通过strkey，获取外部的值
        /// </summary>
        /// <param name="strwhere"></param>
        /// <param name="strcolmun"></param>
        /// <param name="strkey">传递需要通过request捕获的参数</param>
        /// <param name="orand"></param>
        /// <param name="express"></param>
        /// <param name="action"></param>
        /// <param name="orand_end"></param>
        public void querykey(ref String strwhere,
            String strcolmun,
            String strkey,
            orand orand = orand.and,
            express express = express.dengyuzifuchuan,
            Action<WHERE> action = null,
            orand orand_end = orand.and)
        {
            queryvalue(ref strwhere, strcolmun, pagervalue(strkey), orand, express, action, orand_end);
        }

        /// <summary>
        /// 重构函数，主要是如果不传递value值，就用strcolmun取前台参数
        /// </summary>
        /// <param name="strwhere"></param>
        /// <param name="strcolmun"></param>
        /// <param name="orand"></param>
        /// <param name="express"></param>
        /// <param name="action"></param>
        /// <param name="orand_end"></param>
        public void querykey(ref String strwhere,
            String strcolmun,
            orand orand = orand.and,
            express express = express.dengyuzifuchuan,
            Action<WHERE> action = null,
            orand orand_end = orand.and)
        {
            queryvalue(ref strwhere, strcolmun, pagervalue(strcolmun), orand, express, action, orand_end);
        }


        /// <summary>
        /// 组合复杂一点的查询条件，传递的是具体的值，具体的值建议不是从前台捕获的参数
        /// </summary>
        /// <param name="where2"></param>
        /// <param name="strcolmun"></param>
        /// <param name="strvalue"></param>
        /// <param name="orand"></param>
        /// <param name="express"></param>
        /// <param name="action"></param>
        /// <param name="orand_end"></param>
        public void queryvalue(WHERE where2,
            String strcolmun,
            String strvalue,
             orand orand = orand.and,
            express express = express.dengyuzifuchuan,
            Action<WHERE> action = null,
            orand orand_end = orand.and)
        {
            dbdatehelper.querystring(ref where2.where, strcolmun, strvalue, orand, express);

            if (action != null)
            {
                WHERE where = new WHERE();
                action(where);
                if (where.where.isnotnull())
                    where2.where = where2.where + " " + Enum.GetName(typeof(orand), orand_end) + " (" + where.where + ")";
            }
        }

        /// <summary>
        /// 组合where条件，主要是通过strkey，获取外部的值
        /// </summary>
        /// <param name="where2"></param>
        /// <param name="strcolmun"></param>
        /// <param name="strkey">传递需要通过request捕获的参数</param>
        /// <param name="orand"></param>
        /// <param name="express"></param>
        /// <param name="action"></param>
        /// <param name="orand_end"></param>
        public void querykey(WHERE where2,
            String strcolmun,
            String strkey,
            orand orand = orand.and,
            express express = express.dengyuzifuchuan,
            Action<WHERE> action = null,
            orand orand_end = orand.and)
        {
            queryvalue(where2, strcolmun, pagervalue(strkey), orand, express, action, orand_end);
        }

        /// <summary>
        /// 重构函数，主要是如果不传递value值，就用strcolmun取前台参数
        /// </summary>
        /// <param name="where2"></param>
        /// <param name="strcolmun"></param>
        /// <param name="orand"></param>
        /// <param name="express"></param>
        /// <param name="action"></param>
        /// <param name="orand_end"></param>
        public void querykey(WHERE where2,
            String strcolmun,
            orand orand = orand.and,
            express express = express.dengyuzifuchuan,
            Action<WHERE> action = null,
            orand orand_end = orand.and)
        {
            queryvalue(where2, strcolmun, pagervalue(strcolmun), orand, express, action, orand_end);
        }


        /// <summary>
        /// 功能:把对应的键值插入到分页参数中
        /// [09.4.12 lxw]<para />
        /// </summary>
        /// <param name="strKey">request.params[strKey]中的键</param>
        /// <param name="objValue">request.params[strKey]结果</param>
        public void insertpagevalue(String strKey, object objValue)
        {
            string strTemp = "&" + strKey + "=";
            objValue = objValue == null ? "" : objValue;
            if (stringhelper.instr(pagesearchdata, strTemp) == -1)
            {
                pagesearchdata += "&" + strKey + "=" + Server.UrlEncode(objValue.ToString().Trim());
                //如果是这三个值，一定要进行组合
                string strKeys =  string.Format("{0}/{1}/{2}",_ORDER_NAME_,_PAGESIZE_NAME_,_COLUMN_NAME_);
                if (findstr(strKeys, strKey.ToLower(), '/'))
                {
                    pagesortdata += "&" + strKey + "=" + Server.UrlEncode(objValue.ToString().Trim());
                }
            }
        }

        /// <summary>
        /// 为了解决params object[] keys 传递一个字符串的情况
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string removekey(string key)
        {
            return removekey(new object[] { key });
        }

        /// <summary>
        /// 移除对应Key
        /// </summary>
        /// <param name="keys">移除多个键</param>
        /// <returns>返回组合好的字符串</returns>
        public string removekey(params object[] keys)
        {
            string str = this[_PAGESEARCH_NAME_].tostr();
            if (keys == null) return str;

            string[] new_key = new string[keys.Length + 2];
            keys.CopyTo(new_key, 0);
            new_key[keys.Length] = "_lxw_column_searchkeys_";
            new_key[keys.Length] = "_lxw_column_keyvalue_";
            //new_keys.Add("_lxw_column_searchkeys_");
            //new_keys.Add("_lxw_column_keyvalue_");

            //string searchkeys = paramsvalue("_lxw_column_searchkeys_", true);
            //string exp = paramsvalue("_lxw_column_keyvalue_", true);

            Dictionary<string, string> lst = new Dictionary<string, string>();
            foreach (string s in str.Split('&'))
            {
                if (string.IsNullOrEmpty(s)) continue;
                lst[s.Split('=')[0].Trim() + "="] = s;
            }

            foreach (object k in new_key)
            {
                if (lst.ContainsKey(k.tostr().Trim() + "="))
                {
                    //移出
                    lst.Remove(k.tostr().Trim() + "=");
                }
            }

            if (lst.Count == 0) return "_=_";
            return string.Join("&", lst.Values);
        }

        //&_lxw_column_searchkeys_=leixing&_lxw_column_keyvalue_=leixing%3ddengyuzifuchuan
        /// <summary>
        /// 给pagesearch里面插入内容
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public string insertkey(string key, string val)
        {
            string str = this[_PAGESEARCH_NAME_].tostr();
            List<string> lst = new List<string>();
            foreach (string s in str.Split('&'))
            {
                if (string.IsNullOrEmpty(s)) continue;
                if (s.IndexOf(key + "=", StringComparison.OrdinalIgnoreCase) != -1) continue;
                lst.Add(s);
            }

            lst.Add(key + "=" + HttpContext.Current.Server.UrlEncode(val.ToString().Trim()));

            return string.Join("&", lst.ToArray());
        }

       
        /// <summary>
        /// [此方法不再使用]兼容php方法,查找字符串是否在另外一个字符串里面 默认缺省的分隔符为逗号
        /// </summary>
        /// <param name="strsource">源字符串</param>
        /// <param name="strfind">被查找的字符串</param>
        /// <param name="chrsplit">用于分割的字符</param>
        /// <returns>true:存在</returns>
        bool findstr(string strsource, string strfind, char chrsplit = ',')
        {
            if (string.IsNullOrEmpty(strsource) || string.IsNullOrEmpty(strfind))
            {
                return false;
            }

            strfind = strfind.Trim().ToLower();

            string[] strs = strsource.ToLower().Split(chrsplit);
            foreach (string s in strs)
            {
                if (s.Trim().Equals(strfind))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 得到排序字段，先从前台取，如果取不到，就用传过来的值，采用降序 
        /// [2010-01-29 13:52 HanLei]<para />
        /// </summary>
        /// <param name="strColumn">排序字段</param>
        /// <returns></returns>
        public string orderbycolumn(string strColumn)
        {
            return orderbycolumn(strColumn, "desc");
        }

        /// <summary>
        /// 得到排序字段，先从前台取，如果取不到，就用传过来的值 
        /// [2010-01-28 14:12 HanLei]<para />
        /// </summary>
        /// <param name="strColumn">排序字段</param>
        /// <param name="strOrder">排序方式，asc，desc</param>
        /// <returns>返回排序字段</returns>
        public string orderbycolumn(string strColumn, string strOrder)
        {            
            string strValue = getonevalue(_COLUMN_NAME_);
            if (!string.IsNullOrEmpty(strValue))
            {
                strColumn = strValue.Trim();
            }

            strOrder = ordertype(strOrder);

            insertpagevalue(_COLUMN_NAME_, strColumn);
            this[_COLUMN_NAME_] = strColumn;
            return " " + strColumn.Trim() + " " + strOrder;
        }

        /// <summary>
        /// 获取信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        string getonevalue(string key)
        {
            return requesthelper.getonevalue(key);
        }


        /// <summary>
        /// 获取排序方式，先从前台取，如果取不到，就用传过来的值
        /// [2010-01-28 14:21 HanLei]<para />
        /// </summary>
        /// <param name="strOrder">默认排序方式</param>
        /// <returns>返回排序方式</returns>
        public string ordertype(string strOrder = "")
        {            
            string strValue = getonevalue(_ORDER_NAME_);
            if (!string.IsNullOrEmpty(strValue))
            {
                strOrder = strValue;
            }

            strOrder = strOrder.ToLower();
            strOrder = string.IsNullOrEmpty(strOrder) ? "desc" : strOrder;

            insertpagevalue(_ORDER_NAME_, strOrder);
            this[_ORDER_NAME_] = strOrder;

            return strOrder;
        }

        const string _COLUMN_NAME_ = "cn";
        const string _ORDER_NAME_ = "ot";
        const string _PAGESIZE_NAME_ = "ps";
        const string _PAGE_NAME_ = "page";
        /// <summary>
        /// 功能:返回每页显示记录的数量
        /// [09.4.12 lxw]<para />
        /// </summary>
        public int pagesize
        {
            get
            {
                string strValue = getonevalue(_PAGESIZE_NAME_);
                int intDefaultPageSize =
                    cookieshelper.getcookie(_PAGESIZE_NAME_, cookies_domain)
                    .toint32(0);

                if (intDefaultPageSize == 0)
                {
                    //默认为20条的了
                    intDefaultPageSize = pagerinfo.PAGE_SIZE;
                    cookieshelper.setcookie(_PAGESIZE_NAME_, intDefaultPageSize.ToString(), cookies_domain,cookies_expires);
                }

                if (!string.IsNullOrEmpty(strValue))
                {
                    if (intDefaultPageSize.ToString() != strValue)
                    {
                        intDefaultPageSize = strValue.toint32(pagerinfo.PAGE_SIZE);
                        cookieshelper.setcookie(_PAGESIZE_NAME_, intDefaultPageSize.ToString(), cookies_domain, cookies_expires);
                    }
                }

                insertpagevalue(_PAGESIZE_NAME_, intDefaultPageSize);
                return intDefaultPageSize;
            }
        }

        /// <summary>
        /// 得到当前页
        /// </summary>
        /// <returns>返回当前页的数字</returns>
        public int page
        {
            get
            {
                string retPage = "1";
                string strCurPage = getonevalue(_PAGE_NAME_);
                if (!string.IsNullOrEmpty(strCurPage))
                {
                    retPage = strCurPage.Split(',')[0];
                }

                var retPageTrue = Math.Max(1,retPage.toint32(0));
                //insertpagevalue(_PAGE_NAME_, retPageTrue);
                return retPageTrue;
            }
        }

        /// <summary>
        /// 给模板里面输出键值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public object this[string key]
        {
            set
            {
                //如果两次 可能会出现错误
                if (context.ContainsKey(key)) context.Remove(key);
                context.Put(key, value);
            }
            get
            {
                return context.Get(key);
            }
        }

        /// <summary>
        /// 生成排序的字符串
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cn"></param>
        /// <returns></returns>
        public string paixu(string id, string cn)
        {
            return "<span " + formhelper.paixu(
                id, 
                this[_COLUMN_NAME_].tostr(), 
                this[_ORDER_NAME_].tostr())
                + ">" + cn + "</span>&nbsp;";
        }

        //public void putkey(string key, object value)
        //{
        //    if (context.ContainsKey(key)) context.Remove(key);
        //    context.Put(key, value);
        //}
        //public object getkey(string key)
        //{
        //    return context.Get(key);
        //}

        /// <summary>
        /// 格式化金额类
        /// </summary>
        /// <param name="d"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public string formatnumber(object d, int count = 2)
        {
            double x = 0;
            double.TryParse(d.tostr(), out x);

            return x.ToString("F" + count);
        }

        /// <summary>
        /// 格式化日期
        /// </summary>
        /// <param name="date"></param>
        /// <param name="fmt"></param>
        /// <returns></returns>
        public string formatdate(object date, string fmt = "yyyy-MM-dd")
        {
            try
            {
                var v = date.todatetime("", true);
                return v.ToString(fmt);
            }
            catch { }
            return "";
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="number"></param>
        /// <param name="num"></param>
        /// <returns></returns>
        public string formatparcent(object number,int num = 2)
        {
            try
            {
                var v = number.todecimal() * 100;
                return v.ToString("F"+num) + "%";
            }
            catch { }
            return "";
        }

        /// <summary>
        /// 动态解析htm
        /// </summary>
        /// <param name="templatFileName"></param>
        /// <returns></returns>
        public string formatview(string templatFileName)
        {
            //如果存在，才输出到外面
            if (velocity.TemplateExists(templatFileName))
            {
                //从文件中读取模板
                Template template = velocity.GetTemplate(templatFileName);

                //合并模板
                StringWriter writer = new StringWriter();
                template.Merge(context, writer);
                //输出
                return writer.ToString();
            }
            else
            {
                //如果不存在模板，也就不加载layout了。
                return "";
            }
        }

        //解析模板
        //public string formatview(Hashtable has, string templatFileName)
        //{
        //    //如果存在，才输出到外面
        //    if (velocity.TemplateExists(templatFileName))
        //    {
        //        //从文件中读取模板
        //        Template template = velocity.GetTemplate(templatFileName);

        //        IContext cnt = new VelocityContext();

        //        foreach (string key in has.Keys)
        //        {
        //            string value = has[key].tostr();

        //            if (cnt.ContainsKey(key)) cnt.Remove(key);
        //            cnt.Put(key, value);
        //        }


        //        //合并模板
        //        StringWriter writer = new StringWriter();
        //        template.Merge(cnt, writer);
        //        //输出
        //        return writer.ToString();
        //    }
        //    else
        //    {
        //        //如果不存在模板，也就不加载layout了。
        //        return "";
        //    }
        //}

        /// <summary>
        /// 输出模板信息
        /// </summary>
        /// <param name="templatFileName">模板后缀</param>
        private void display(string templatFileName)
        {           
            if (_cancelview) return;

            //删除后缀
            if(templatFileName.Contains("."))
            {
                if (templatFileName.EndsWith(".html", StringComparison.OrdinalIgnoreCase))
                    templatFileName = templatFileName.Remove(templatFileName.Length - 5);

                if (templatFileName.EndsWith(".htm", StringComparison.OrdinalIgnoreCase))
                    templatFileName = templatFileName.Remove(templatFileName.Length - 4);

                if (templatFileName.EndsWith(".vm", StringComparison.OrdinalIgnoreCase))
                    templatFileName = templatFileName.Remove(templatFileName.Length - 3);
            }

            string bodyhtml = "";

            var htmls = new string[] { ".htm", ".html", ".vm" };
            foreach (var ext in htmls)
            {
                //如果存在，才输出到外面
                if (velocity.TemplateExists(templatFileName+ext))
                {
                    //从文件中读取模板
                    Template template = velocity.GetTemplate(templatFileName + ext);
                    //合并模板
                    StringWriter writer = new StringWriter();
                    template.Merge(context, writer);
                    //输出
                    bodyhtml = writer.ToString();
                    break;
                }
                else
                {
                    //如果不存在模板，也就不加载layout了。
                    return;
                }
            }

            var layouthtml = bodyhtml;
            if (layoutname != "")
            {
                foreach (var ext in htmls)
                {
                    string viewpath = "/layout/" + layoutname + ext;
                    if (velocity.TemplateExists(viewpath))
                    {
                        //从文件中读取模板
                        Template template = velocity.GetTemplate(viewpath);

                        //合并模板
                        StringWriter writer = new StringWriter();
                        this["bodycontent"] = bodyhtml;
                        template.Merge(context, writer);
                        //输出
                        layouthtml = writer.ToString();
                        break;
                    }
                }
            }

            //输出内容
            Response.Write(
                jqueryfmt(layouthtml)
                );
        }

        /// <summary>
        /// 处理$. $(的东西，这是jquery的写法
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        string jqueryfmt(string p)
        {
            return p;
            //防止前面计息不了jquery的东西,这里很变态，主要是处理前面模板中可能存在的错误信息
            //return p.Replace("." + NVelocity.App.Velocity.jquery_token, "$.").Replace(NVelocity.App.Velocity.jquery_token, "");
        }
        /// <summary>
        /// 查询关键字
        /// </summary>
        const string _sw_ = "_sw_";
        /// <summary>
        /// 需要保存状态的key
        /// </summary>
        const string _sk_ = "_sk_";
        /// <summary>
        /// 组合查询语句
        /// </summary>
        /// <returns></returns>
        public string search(string where = "")
        {

            string searchkeys = paramsvalue("_lxw_column_searchkeys_", true);
            string exp = paramsvalue("_lxw_column_keyvalue_", true).Replace("&gt;", ">");

            //移除这些不要的键
            //removekey("_lxw_column_searchkeys_", "_lxw_column_keyvalue_");

            ////如果不是post的时候，直接获取where数据
            ////这部分有点凑数的感觉，目前没有好的想法
            //if (Request.ServerVariables["REQUEST_METHOD"].ToUpper() == "GET")
            //{
            //    //还原where语句
            //    if (v_s(_sw_).Length > 0)
            //        where = cryptohelper.decode(v_s(_sw_));

            //    //还原查找语句，其实基本上用不到，只是用于保存状态而已
            //    string keys = v_s(_sk_);
            //    if (keys.Length > 0)
            //    {
            //        this.insertpagevalue(_sk_, keys);
            //        foreach (var k in keys.Split(','))
            //            this.insertpagevalue(k, v_s(k));
            //    }                
            //}
            //else
            {
                //这部分是查询语句，必须通过post方式提交过来的。
                //string keys = "";
                foreach (string s in searchkeys.Split(','))
                {
                    if (string.IsNullOrEmpty(s)) continue;
                    express expr = (express)Enum.Parse(typeof(express), requesthelper.fromurlparamsgetvaluebykey(exp, s, ">"));
                    //switch (expr)
                    //{
                    //    case express.dengyuriqi:
                    //    case express.budengyuriqi:
                    //    case express.dayuriqi:
                    //    case express.xiaoyuriqi:
                    //    case express.dayudengyuriqi:
                    //    case express.xiaoyudengyuriqi:
                    //        dbdatehelper.querydatetime(ref where,s,para
                    //}
                    //这里必须获取的是form的值
                    string str = paramsvalue(s, true);

                    //插入到查询条件中
                    //this.insertpagevalue(s, str);
                    //保持状态，前台能使用
                    //this[s] = str;

                    //keys += "," + s;
                    dbdatehelper.querystring(ref where, s, str, orand.and, expr);
                }

                //把查询关键字放入条件中
                //if (keys.Length > 0)
                //    this.insertpagevalue(_sk_, keys.Substring(1));
            }

            //把组合好的where语句加密放入查询条件中
            //if (where.Length > 0)
            //    this.insertpagevalue(_sw_, cryptohelper.encode(where));

            return where;
        }

        /// <summary>
        /// response.write  信息到浏览器
        /// </summary>
        /// <param name="p">内容</param>
        /// <param name="arg">可能内容存在需要替换的参数</param>
        public void write(string p, params object[] arg)
        {
            if (arg != null && arg.Length > 0)
                p = string.Format(p, arg);

            Response.StatusCode = 200;
            Response.Write(p);
            
            //如果输出 就不要显示模板
            this.cancelview();
        }

        /// <summary>
        /// 执行这个，会抛出线程终止错误ThreadAbortException 需要用这个捕获
        /// </summary>
        /// <param name="p"></param>
        /// <param name="arg"></param>
        public void writeend(string p, params object[] arg)
        {
            write(p, arg);
            Response.End();
        }

        ///// <summary>
        ///// 提示信息
        ///// </summary>
        ///// <param name="p"></param>
        //public void alert(string p)
        //{
        //    Response.Write("alert(\'" + p.Replace("'", "\"") + "\');");
        //    //如果输出 就不要显示模板
        //    this.cancelview();
        //}



        ///// <summary>
        ///// 提示信息，并转向，注意，只是针对前面form.submit提交才有用
        ///// </summary>
        ///// <param name="url"></param>
        ///// <param name="msg"></param>
        //public void topage(string url, string msg = "")
        //{
        //    string text = string.IsNullOrEmpty(msg) ? "" : "alert('" + msg.Replace("'", "\'") + "');";
        //    text += "location.href='" + url + "';";
        //    Response.Write(text);
        //}

        ///// <summary>
        ///// 得到字典集合
        ///// </summary>
        ///// <param name="bianma"></param>
        ///// <param name="paixu"></param>
        ///// <returns></returns>
        //public DataRowCollection getzidianrows(string bianma, string paixu = "")
        //{
        //    string sql = "select * from zidian where zidianleibieid in(select zidianleibieid from zidianleibie where bianma='" + bianma + "') " + paixu;
        //    return jiandansql.getrows(sql);
        //}

        ///// <summary>
        ///// 通过表得到信息
        ///// </summary>
        ///// <param name="tablename"></param>
        ///// <param name="paixu"></param>
        ///// <returns></returns>
        //public DataRowCollection gettablerows(string tablename, string paixu = "")
        //{
        //    string sql = "select * from " + tablename + " " + paixu;
        //    return jiandansql.getrows(sql);
        //}

        /// <summary>
        /// 重定向到对应的页面,所有提交的信息都已经保留。
        /// </summary>
        /// <param name="url">重定向的URL</param>
        /// <param name="endresponse">是否终止请求，false 不终止</param>
        public void redirect(string url, bool endresponse = false)
        {
            cancelview();
            Response.Redirect(url, endresponse);

            return;
        }

        /// <summary>
        /// 设置table和id
        /// </summary>
        /// <param name="p"></param>
        public void settable(string p)
        {
            if (!supermodel.pks.ContainsKey(p))
                throw new Exception("MMM:"+p+"没有找到对应的主键！");
            //获取主键
            pk = supermodel.pks[p];
            table = p;
            //把主键输出到界面中
            this["pk"] = pk;
        }

        /// <summary>
        /// 判断是否是post请求
        /// </summary>
        public bool Post
        {
            get
            {
                return Request.HttpMethod.ToUpper() == "POST";
            }
        }

        /// <summary>
        /// 获取页面传输过来的json对象
        /// </summary>
        public T v_json<T>(string key = "")
        {
            try
            {
                if (string.IsNullOrEmpty(key))
                {
                    StreamReader sb = new StreamReader(Request.InputStream, Encoding.UTF8);
                    var content = sb.ReadToEnd();

                    return (T)JavaScriptConvert.DeserializeObject(
                        content
                        );
                }

                return (T)JavaScriptConvert.DeserializeObject(
                    v_s(key)
                    ) ;

            }
            catch { }
            return default(T);
        }


        /// <summary>
        /// 输出json对象或者json字符串
        /// </summary>
        /// <param name="p"></param>
        public void json<T>(T p)
        {
            Response.ContentType = "application/json";
            if (typeof(T).IsClass)
                write(JavaScriptConvert.SerializeObject(p));
            else
                write(p.tostr());
            //Content-Type: application/json; charset=utf-8
        }



        /// <summary>
        /// request
        /// </summary>
        public HttpRequest Request { get; set; }

        /// <summary>
        /// response
        /// </summary>
        public HttpResponse Response { get; set; }

        /// <summary>
        /// session
        /// </summary>
        public System.Web.SessionState.HttpSessionState Session { get; set; }
        /// <summary>
        /// server
        /// </summary>
        public HttpServerUtility Server { get; set; }
        /// <summary>
        /// context
        /// </summary>
        public HttpContext Context { get; set; }

        /// <summary>
        /// 释放
        /// </summary>
        ~pagebase()
        {
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放
        /// </summary>
        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 请输入正确的手机号
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="p"></param>
        public void ifmobile(string mobile, string p)
        {
            Regex regex = new Regex("^1\\d{10}$");
            ifcheck(!regex.IsMatch(mobile), p);
        }

        /// <summary>
        /// 请输入正确的email
        /// </summary>
        /// <param name="email"></param>
        /// <param name="p"></param>
        public void ifemail(string email, string p)
        {
            Regex regex = new Regex("^\\s*([A-Za-z0-9_-]+(\\.\\w+)*@(\\w+\\.)+\\w{2,5})\\s*$");
            ifcheck(!regex.IsMatch(email), p);
        }
    }

    /// <summary>
    /// 退出异常类
    /// </summary>
    public class ExitException : Exception
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public ExitException() : base() { }
    }
}